package com.dragon.modules.yuegou.mybatis;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonUnwrapped;
import org.apache.commons.collections4.CollectionUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * 条件
 * 
 * @author liuwu
 * 
 * @param <T>
 */
@JsonInclude(Include.NON_NULL)
public class Condition<T extends Comparable<? super T>> {


	/**
	 * Equal
	 */
	@JsonProperty("Eq")
	private T eq;

	/**
	 * Not Equal
	 */
	@JsonProperty("Ne")
	private T ne;

	/**
	 * Greater Than
	 */
	@JsonProperty("Gt")
	private T gt;

	/**
	 * Less Than
	 */
	@JsonProperty("Lt")
	private T lt;

	/**
	 * Greater Equal
	 */
	@JsonProperty("Ge")
	private T ge;

	/**
	 * Less Equal
	 */
	@JsonProperty("Le")
	private T le;

	/**
	 * In
	 */
	@JsonProperty("In")
	private List<T> in;

	/**
	 * Not In 
	 */
	@JsonProperty("NotIn")
	private List<T> notIn;

	/**
	 * Between
	 */
	@JsonUnwrapped(prefix = "Between")
	private Between<T> between;

	/**
	 * Like
	 */
	@JsonProperty("Like")
	private String like;
	
	/**
	 * Not Like
	 */
	@JsonProperty("NotLike")
	private String notLike;

	/**
	 * Like Left
	 */
	@JsonProperty("LikeLeft")
	private String likeLeft;

	/**
	 * Like Right
	 */
	@JsonProperty("LikeRight")
	private String likeRight;
	
	/**
	 * Like Right
	 */
	@JsonProperty("IsNull")
	private Boolean isNull;

	/**
	 * 构造一个空条件对象
	 */
	public Condition() {
		super();
	}

	/**
	 * 依据另一个条件对象构造一个新的条件对象
	 * 
	 * @param other 另一个条件对象
	 */
	public Condition(Condition<T> other) {
		super();
		this.eq = other.eq;
		this.ne = other.ne;
		this.gt = other.gt;
		this.lt = other.lt;
		this.ge = other.ge;
		this.le = other.le;
		this.isNull = other.isNull;
		if (other.in != null) {
			this.in = new ArrayList<>(other.in);
		}
		if (other.notIn != null) {
			this.notIn = new ArrayList<>(other.notIn);
		}
		if (other.between != null) {
			this.between = new Between<>(other.between.getFrom(), other.between.getTo());
		}
		this.like = other.like;
		this.notLike = other.notLike;
		this.likeLeft = other.likeLeft;
		this.likeRight = other.likeRight;
	}
	
	@JsonIgnore
	public Condition<T> isNull() {
		this.isNull = true;
		return this;
	}

	@JsonIgnore
	public Condition<T> isNotNull() {
		this.isNull = false;
		return this;
	}

	public Condition<T> eq(T val) {
		this.eq = val;
		return this;
	}

	public Condition<T> ne(T val) {
		this.ne = val;
		return this;
	}

	public Condition<T> gt(T val) {
		this.gt = val;
		return this;
	}

	public Condition<T> lt(T val) {
		this.lt = val;
		return this;
	}

	public Condition<T> ge(T val) {
		this.ge = val;
		return this;
	}

	public Condition<T> le(T val) {
		this.le = val;
		return this;
	}

	public Condition<T> in(List<T> vals) {
		this.in = vals;
		return this;
	}

	public Condition<T> notIn(List<T> vals) {
		this.notIn = vals;
		return this;
	}

	public Condition<T> between(T from, T to) {
		this.between = new Between<>(from, to);
		return this;
	}

	public Condition<T> like(String val) {
		this.like = val;
		return this;
	}
	
	public Condition<T> notLike(String val) {
		this.notLike = val;
		return this;
	}

	public Condition<T> likeLeft(String val) {
		this.likeLeft = val;
		return this;
	}

	public Condition<T> likeRight(String val) {
		this.likeRight = val;
		return this;
	}

	public void toWrapper(QueryWrapper<?> wrapper, String column) {
		if(isNull != null) {
			if(isNull) {
				wrapper.isNull(column);
			}else {
				wrapper.isNotNull(column);
			}
		}
		if (ObjectHelper.isNotEmpty(eq)) {
			wrapper.eq(column, eq);
		}
		if (ObjectHelper.isNotEmpty(like)) {
			wrapper.like(column, like);
		}
		if (ObjectHelper.isNotEmpty(likeLeft)) {
			wrapper.likeLeft(column, likeLeft);
		}
		this.setWrapper(wrapper,column);
	}

	private void setWrapper(QueryWrapper<?> wrapper, String column){
		if (ObjectHelper.isNotEmpty(likeRight)) {
			wrapper.likeRight(column, likeRight);
		}
		if (ObjectHelper.isNotEmpty(ne)) {
			wrapper.ne(column, ne);
		}
		if (ObjectHelper.isNotEmpty(gt)) {
			wrapper.gt(column, gt);
		}
		if (ObjectHelper.isNotEmpty(lt)) {
			wrapper.lt(column, lt);
		}
		if (ObjectHelper.isNotEmpty(ge)) {
			wrapper.ge(column, ge);
		}
		if (ObjectHelper.isNotEmpty(le)) {
			wrapper.le(column, le);
		}
		if (CollectionUtils.isNotEmpty(in)) {
			wrapper.in(column, in);
		}
		if (CollectionUtils.isNotEmpty(notIn)) {
			wrapper.notIn(column, notIn);
		}
		if (ObjectHelper.isNotEmpty(between) && between.isNotEmpty()) {
			wrapper.between(column, between.getFrom(), between.getTo());
		}
	}

	/**
	 * 复制条件对象
	 * 
	 * @return 复制后的新条件对象
	 */
	public Condition<T> copy() {
		return new Condition<>(this);
	}

	public T getEq() {
		return eq;
	}

	public void setEq(T eq) {
		this.eq = eq;
	}

	public T getNe() {
		return ne;
	}

	public void setNe(T ne) {
		this.ne = ne;
	}

	public T getGt() {
		return gt;
	}

	public void setGt(T gt) {
		this.gt = gt;
	}

	public T getLt() {
		return lt;
	}

	public void setLt(T lt) {
		this.lt = lt;
	}

	public T getGe() {
		return ge;
	}

	public void setGe(T ge) {
		this.ge = ge;
	}

	public T getLe() {
		return le;
	}

	public void setLe(T le) {
		this.le = le;
	}

	public List<T> getIn() {
		return in;
	}

	public void setIn(List<T> in) {
		this.in = in;
	}

	public List<T> getNotIn() {
		return notIn;
	}

	public void setNotIn(List<T> notIn) {
		this.notIn = notIn;
	}

	public Between<T> getBetween() {
		return between;
	}

	public void setBetween(Between<T> between) {
		this.between = between;
	}

	public String getLike() {
		return like;
	}

	public void setLike(String like) {
		this.like = like;
	}

	public String getNotLike() {
		return notLike;
	}

	public void setNotLike(String notLike) {
		this.notLike = notLike;
	}

	public String getLikeLeft() {
		return likeLeft;
	}

	public void setLikeLeft(String likeLeft) {
		this.likeLeft = likeLeft;
	}

	public String getLikeRight() {
		return likeRight;
	}

	public void setLikeRight(String likeRight) {
		this.likeRight = likeRight;
	}

	/**
	 * （二元）操作符
	 * 
	 * @author liuwu
	 *
	 */
	enum Op {

		EQ(),
		NE(),
		GT() ,
		LT() ,
		GE() ,
		LE() ,
		LIKE() ,
		NOT_LIKE(),
		LIKE_LEFT() ,
		LIKE_RIGHT(),
		IN() ,
		NOT_IN();
	}

	/**
	 * 三元操作符
	 * 
	 * @author liuwu
	 *
	 */
	enum ThOp {

		BETWEEN();

	}

}
